﻿
using System.Drawing;
using System.Windows.Forms;


namespace AE_Installs
{
    /// <summary>
    /// 自定义TreeView控件，支持节点级别的复选、单选；
    /// 节点显示样式改为Icon+CheckBox+NodeText的样式
    /// </summary>
    public class GTreeView : TreeView
    {
        #region Private Variables

        private const int checkBoxImageWidth = 16;
        private const int checkBoxImageHeight = 16;
        private Image imgChecked;
        private Image imgUnchecked;
        private Image imgRBChecked;
        private Image imgRBUnchecked;
        private System.ComponentModel.IContainer components;
        #endregion

        #region Constructs
        public GTreeView(System.ComponentModel.ComponentResourceManager Resource)
        {
            InitializeComponent();

            // 初始化CheckBox相关的图片
            imgUnchecked = Resource.TreeNodeUnchecked;
            imgChecked = Resource.TreeNodeChecked;
            imgRBUnchecked = Resource.TreeNodeRBUnchecked;
            imgRBChecked = Resource.TreeNodeRBChecked;

            // 设置TreeView为自己绘制文本和图标并绑定相关的事件
            this.DrawMode = TreeViewDrawMode.OwnerDrawText;
            this.DrawNode += new DrawTreeNodeEventHandler(GTreeView_DrawNode);
            this.MouseUp += new MouseEventHandler(GTreeView_MouseUp);
        }

        #endregion

        #region Event Hanlder Methods

        /// <summary>
        /// 判断如果点击的是Checkbox图片，则改变节点的IsCheck属性值
        /// 需要注意的是同一父节点下只允许一个RadioButton类型的节点为选中状态
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void GTreeView_MouseUp(object sender, MouseEventArgs e)
        {
            GTreeNode node = GetNodeAt(e.X, e.Y) as GTreeNode;
            if (node == null || !node.CheckBoxVisible)
            {
                return;
            }
            Rectangle checkboxImgRect = new Rectangle(node.Bounds.X, node.Bounds.Y, checkBoxImageWidth, checkBoxImageHeight);     //节点区域

            // 如果点击的是checkbox图片
            if (checkboxImgRect.Contains(e.X, e.Y))
            {
                node.Checked = !node.Checked;

                // 如果是单选，则设置同级别的其它单选项为unchecked.
                if (node.Parent != null && node.CheckBoxStyle == GTreeNode.CheckBoxStyleEnum.RadioButton)
                {
                    foreach (TreeNode siblingNode in node.Parent.Nodes)
                    {
                        var siblingGNode = siblingNode as GTreeNode;
                        if (siblingGNode == null)
                        {
                            continue;
                        }
                        if (siblingGNode.Name != node.Name && siblingGNode.CheckBoxStyle == GTreeNode.CheckBoxStyleEnum.RadioButton && siblingGNode.Checked)
                        {
                            siblingGNode.Checked = false;
                        }

                    }
                }
            }
        }

        /// <summary>
        /// 绘制节点的图标和文字，样式为Icon+CheckBox+NodeText
        /// Checkbox支持节点级别的单选、复选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void GTreeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
        {
            GTreeNode node = e.Node as GTreeNode;
            if (node == null)
            {
                return;
            }

            Rectangle nodeRect = e.Node.Bounds;

            // 如果需要显示CheckBox,则绘制
            if (node.CheckBoxVisible)
            {
                Point drawPt = new Point(nodeRect.Location.X, nodeRect.Location.Y);     //绘制图标的起始位置
                Size imgSize = new Size(checkBoxImageWidth, checkBoxImageHeight);        //图片大小
                Rectangle imgRect = new Rectangle(drawPt, imgSize);

                if (e.Node.Checked)
                {
                    if (node.CheckBoxStyle == GTreeNode.CheckBoxStyleEnum.CheckBox)
                    {
                        e.Graphics.DrawImage(imgChecked, imgRect);
                    }
                    else
                    {
                        e.Graphics.DrawImage(imgRBChecked, imgRect);

                    }
                }
                else
                {
                    if (node.CheckBoxStyle == GTreeNode.CheckBoxStyleEnum.CheckBox)
                    {
                        e.Graphics.DrawImage(imgUnchecked, imgRect);
                    }
                    else
                    {
                        e.Graphics.DrawImage(imgRBUnchecked, imgRect);
                    }
                }
            }



            //-----------------------绘制文本 -------------------------------
            Rectangle textRec;
            if (node.CheckBoxVisible)
            {
                textRec = new Rectangle(nodeRect.X + checkBoxImageWidth + 2, nodeRect.Y, nodeRect.Width, nodeRect.Height);
            }
            else
            {
                textRec = nodeRect;
            }

            Font nodeFont = e.Node.NodeFont;
            if (nodeFont == null)
                nodeFont = ((TreeView)sender).Font;
            Brush textBrush = SystemBrushes.WindowText;

            if ((e.State & TreeNodeStates.Focused) != 0)
            {
                e.Graphics.FillRectangle(SystemBrushes.Highlight, textRec);
            }
            e.Graphics.DrawString(e.Node.Text, nodeFont, textBrush, Rectangle.Inflate(textRec, 2, 0));


        }

        /// <summary>
        /// 节点被选中后，如果节点有事件处理程序，则调用 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnAfterSelect(TreeViewEventArgs e)
        {
            var gNode = e.Node as GTreeNode;
            if (gNode != null && gNode.NodeSelected != null)
            {
                TreeViewEventArgs arg = new TreeViewEventArgs(e.Node);
                gNode.NodeSelected(this, arg);
                return;
            }
            base.OnAfterSelect(e);
        }

        #endregion

        #region Private Methods
        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // GTreeView
            // 
            this.LineColor = System.Drawing.Color.Black;
            this.ResumeLayout(false);

        }
        #endregion

    }

}
